/*
 * DisplayTask.java
 * 
 * last update: 16.01.2010 by Stefan Saru
 * 
 * author:	Alec(panovici@elcom.pub.ro)
 * 
 * Obs:
 */

package engine;
import java.util.*;

/**
 * This is the implementation of the <code>$display</code> task.
 * Other tasks, such as <code>$strobe, $write</code> && stuff may also use this
 * as a starting point.
 */

class DisplayTask extends DefaultInstruction{
	Vector target;
	int defaultBase;

	DisplayTask(NameSpace ns, int delayBefore,
			InstructionDescription desc, int defaultBase,
			Vector target, Instruction next){
		super(ns, delayBefore, desc);
		this.target = target;
		this.defaultBase = defaultBase;
		add(next);
	}

	DisplayTask(DisplayTask dt){
		this(dt.ns, dt.delayBefore, dt.desc, dt.defaultBase, dt.target, dt.next);
	}

	public void execute()
	throws InterpretTimeException, SimulationStoppedException
	{
		waitToRun();
		xConsole.trace(this + "");
		String output = "", format = null, s;
		for(Enumeration e = target.elements(); e.hasMoreElements(); ) {
			Object o = e.nextElement();
			if (o == null) output += " ";
			else 
				if (o instanceof String) {
					s = o.toString();
					if (s.equals("%m") || s.equals("%M")) output += ns.toString();
					else if (s.startsWith("%")) format = s;
					else output += s;
				} else { // expression
					if((format != null) && (format.equalsIgnoreCase("%v"))){
						//strength:
						WireSelection se = (WireSelection) o;  //type is checked
						//in instantiate
						if(se.length() > 1){
							output += "{";
							for(int bit = se.length()-1 ; ; bit--){
								int strength;
								try{
									strength = se.getStrength(bit);
								}catch(ClassCastException cex){
									throw new
									InterpretTimeException(desc + ": error: a wire or wire concatenation must be used with %V format spec");
								}
								output += Strength.
								strengthToString((byte) (strength & 0xff), strength >> 16);
								if(bit == 0)break;
								output += ", ";
							}
							output += "}";
						}else{
							int strength = se.getStrength(0);
							output += Strength.
							strengthToString((byte) (strength & 0xff), strength >> 16);
						}
					}else{
						Result rs = null;
						try{
							rs = ((Expression)o).evaluate();
						}catch(InterpretTimeException ex){
							xConsole.dumpStack(ex);
							throw new InterpretTimeException(desc + ": error:" + ex);
						}
						xConsole.debug("$display: " + rs);
						if (format == null) output += rs.toString(defaultBase);
						else output += format(rs, format.charAt(1));
						format = null;
					}
				}
		}
		xConsole.display(output);
	}

	String format(Result rs, char f) {
		switch (f) {
		case 'h': case 'H': return rs.toString(16);
		case 'd': case 'D': return rs.toString(10);
		case 'o': case 'O': return rs.toString(8);
		case 'b': case 'B': return rs.toString(2);
		case 'v': case 'V':
			xConsole.debug("WARNING: DisplayTask.format with argument %V");
			break; //this is handled inside execute !
		case 's': case 'S': return rs.toString(256); // in format String
		case 't': case 'T': return "" + rs.getLong();
		case 'c': case 'C': {
			String r = rs.toString(256);
			return r.substring(0,1);
		}
		case 'e': case 'E': return rs.getReal().toString();  // ieee 754
		case 'f': case 'F': return rs.getReal().toDecimalString(); // a.b
		case 'g': case 'G':
			String s1 = rs.getReal().toString(), s2 = rs.getReal().toDecimalString();
			return (s1.length() < s2.length() ? s1 : s2);
		}
		return "[?]";
	}

	public String toString(){
		return desc.toString();
	}
}

